﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Company.Project.Domain.Base;
using Company.Project.Domain.MainModule.Interface;
using Company.Project.Domain.Model;
using Company.Project.Domain.Model.DTO.Manager;
using Company.Project.Infrastructure.Repository.Sqlserver.DataBaseFactory;
using Company.Project.Infrastructure.Repository.Sqlserver.RepositoriesBase;
using Company.Utility.Extensions;
using Microsoft.EntityFrameworkCore;

namespace Company.Project.Infrastructure.Repository.Sqlserver
{
    public class Project_SYS_ModuleRepository : RepositoryBase<Project_SYS_Module>, IProject_SYS_ModuleRepository
    {
        public Project_SYS_ModuleRepository(IDatabaseFactory databaseFactory)
            : base(databaseFactory)
        {

        }
        public async Task<List<MenuModuleListDTO>> LoadModuleList(Guid RoleId)
        {
            var source = await (from a in dbset.OrderBy(x => x.OrderID).Include(x => x.ModuleActions)
                    .ThenInclude(x => x.Module).Where(x => !x.IsDeleted)
                select new { a.ModuleName, a.ID, a.ModuleActions, a.PID }).ToListAsync();
            var result = new List<MenuModuleListDTO>();
            source.ForEach(a =>
            {
                if (a.PID == Guid.Empty)
                {
                    var model = new MenuModuleListDTO()
                    {
                        ModuleName = a.ModuleName,
                        ChildModule = source.Where(x => x.PID == a.ID).Select(x => new MenuChildModuleListDTO()
                        {
                            ModuleName = x.ModuleName,
                            ChildAction =
                                x.ModuleActions.OrderBy(y => y.OrderID)
                                    .Where(y => !y.IsDeleted)
                                    .Select(y => new MenuChildActionListDTO()
                                    {
                                        ActionName = y.ActionName,
                                        ModuleId = y.ModuleID,
                                        ID = y.ID,
                                        IsCheck = false,
                                        Weight = y.Weight,
                                        IsMenu = y.ShowEnum
                                    }).ToList(),
                            ThreeChildModule = source.Where(y => y.PID == x.ID).Select(y => new MenuThreeChildModuleListDTO()
                            {
                                ModuleName = y.ModuleName,
                                ChildAction =
                                    y.ModuleActions.OrderBy(z => z.OrderID)
                                        .Where(z => !z.IsDeleted)
                                        .Select(z => new MenuChildActionListDTO()
                                        {
                                            ActionName = z.ActionName,
                                            ModuleId = z.ModuleID,
                                            ID = z.ID,
                                            IsCheck = false,
                                            Weight = z.Weight,
                                            IsMenu = z.ShowEnum
                                        }).ToList(),
                            }).ToList()
                        }).ToList()
                    };
                    result.Add(model);
                }
            });
            if (RoleId != Guid.Empty)
            {
                var roleList =await 
                    (from a in DataContext.Project_SYS_Role.Where(x => !x.IsDeleted && x.ID == RoleId).Include(x=>x.RoleActions).ThenInclude(x=>x.Role)
                        select new {a.RoleActions}).FirstOrDefaultAsync();
                result.ForEach(x => x.ChildModule.ToList().ForEach(y =>
                {
                    if (y.ChildAction != null && y.ChildAction.Any())
                    {
                        y.ChildAction.ToList().ForEach(z =>
                        {
                            roleList?.RoleActions?.ToList().ForEach(m =>
                            {
                                if (z.ModuleId == m.ModuleID)
                                {
                                    z.IsCheck = ((m.Weight & z.Weight) == z.Weight);
                                }
                            });
                        });
                    }
                    else if (y.ThreeChildModule != null && y.ThreeChildModule.Any())
                    {
                        y.ThreeChildModule.ToList().ForEach(z =>
                        {
                            if (z.ChildAction != null && z.ChildAction.Any())
                            {
                                z.ChildAction.ToList().ForEach(n =>
                                {
                                    roleList?.RoleActions?.ToList().ForEach(m =>
                                    {
                                        if (n.ModuleId == m.ModuleID)
                                        {
                                            n.IsCheck = ((m.Weight & n.Weight) == n.Weight);
                                        }
                                    });
                                });
                            }
                        });
                    }
                }));
            }
            return result;
        }

        public async Task<dynamic> GetFatherModule(Guid fatherId, Guid itemId)
        {
            var def = new List<dynamic> {new {Text = "顶级目录", Value = Guid.Empty, Selected = true, PID = Guid.Empty}};
            var space = "&nbsp;&nbsp;";
            var allModule =(await GetManyAsync(
                new DirectSpecification<Project_SYS_Module>(x => !x.IsDeleted)))
                .Select(
                    x =>
                        new
                        {
                            Text = (x.PID == Guid.Empty ? space + "├" : space + space + "├") + x.ModuleName,
                            Value = x.ID,
                            Selected = false,
                            x.PID
                        });
            allModule.Where(x => x.PID == Guid.Empty).ToList().ForEach(x =>
            {
                if (fatherId == x.Value)
                {
                    def.Add(new {x.Text, x.Value, Selected = true, PID = Guid.Empty});
                }
                else
                {
                    def.Add(x);
                }
                allModule.Where(y => y.PID == x.Value).ToList().ForEach(y =>
                {
                    if (fatherId == y.Value)
                    {
                        def.Add(new {y.Text, y.Value, Selected = true, PID = Guid.Empty});
                    }
                    else
                    {
                        def.Add(y);
                    }
                });
            });
            return def;
        }
        /// <summary>
        /// 递归获取模块
        /// </summary>
        /// <returns></returns>
        public async Task<IEnumerable<RecursiveModuleDTO>> GetModuleByRecursive(Guid? Id = null)
        {
            var query =
                "with cte as(select *,0 as Level from Project_SYS_Module where PID =CONVERT([UNIQUEIDENTIFIER],CONVERT([BINARY],(0),(0)),(0)) union all select d.*, Level+1 from cte c inner join Project_SYS_Module d on c.Id = d.Pid) select * from cte where IsDeleted=0";
            var all = await Task.Run(() => DataContext.SqlQuery<RecursiveModuleDTO>(query, null).AsEnumerable());
            if (Id == null)
            {
                return all;
            }
            else
            {
                return all.Where(x => x.ID == Id);
            }
        }

        public async Task<EntityList<ModuleDTO>> GetModuleList(int page, int rows, ISpecification<Project_SYS_Module> specification,
            Dictionary<string, string> sort)
        {
            var query = (from a in dbset.Where(specification.SatisfiedBy())
                         let b= (from b in dbset.Where(x => !x.IsDeleted && x.PID==a.ID) select b)
                         select new ModuleDTO()
                         {
                             ID = a.ID,
                             ModuleName = a.ModuleName,
                             OrderID = a.OrderID,
                             ChildModuleCount=b.Count(),
                             ModuleCls = a.ModuleCls
                         });
            return await FindAllAsyncAsQuery(DataSort(query, sort), page, rows);
        }

        public async Task<List<Project_SYS_Module>> GetLoginModule()
        {
            return await (from a in dbset.Where(x => !x.IsDeleted).Include(x => x.ModuleActions)
                    .ThenInclude(x => x.Module)
                select a
            ).OrderBy(x => x.OrderID).ToListAsync();
        }
    }
}

